package com.walker.taogong.hibernate.impl;

import java.net.URL;
import java.util.List;
import java.util.Vector;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.walker.taogong.datasource.DataSourceProvider;
import com.walker.taogong.hibernate.MappingProvider;
import com.walker.taogong.hibernate.SessionFactoryProvider;


/**
 * TODO: describe me
 *
 */
public class SessionFactoryProviderImpl implements SessionFactoryProvider
{
    private static Logger log = LoggerFactory.getLogger(SessionFactoryProvider.class);
    private String dialect;
    private ComponentContext context;
    
    private static List<MappingProvider> mappingProviders = new Vector<MappingProvider>();
    
    /** 根据mapping provider的变化来动态更新SessionFactoryProvider*/
    private boolean isUpdated = false;
    
    public SessionFactoryProviderImpl()
    {
    }

    private DataSourceProvider dataSource;
//    
//    public DataSourceProvider getDataSource() {
//		return dataSource;
//	}
//    
//	public void setDataSource(DataSourceProvider dataSource) {
//		this.dataSource = dataSource;
//	}

//    public void activate()
    protected void activate(ComponentContext compContext)
    {
        log.info("activating SessionFactoryProvider");
        this.context = compContext;
//        compContext.locateService("DataSourceProvider");
        dataSource = (DataSourceProvider) context.locateService("DataSourceProvider");
        dataSource.registerDataSource();
    }
    
    protected void addMap(MappingProvider mappingProvider)
    {
//        String name = (String) mappingProvider.get("name");
        log.info("added mapping service {}", mappingProvider.toString());
        mappingProviders.add(mappingProvider);
        isUpdated=true;
    }
    
    protected void removeMap(MappingProvider mappingProvider)
    {
    	log.info("removed mapping service {}", mappingProvider.toString());
    	mappingProviders.remove(mappingProvider);
    	isUpdated=true;
    }

    @Override
    public SessionFactory getSessionFactory()
    {
        log.info("getSessionFactory()");
        URL url = getClass().getResource("/hibernate.cfg.xml");
        // create session factory from config file
        Configuration hibernateConfig = new Configuration().configure(url);

//        AnacondaConfigManager cm = (AnacondaConfigManager) context.locateService("ConfigManager");
//        AnacondaSettings anacondaConfig = cm.getConfiguration(null); 
        
//        DataSourceProvider dsProvider = (DataSourceProvider) context.locateService("DataSourceProvider");
//        dsProvider.registerDataSource();
        
//        HibernateSettings hibernateSettings = anacondaConfig.getServer().getHibernate();
//        dialect = hibernateSettings.getDialect();
        dialect = "org.hibernate.dialect.PostgreSQLDialect";
//        if(hibernateSettings.isGenerateStatistics() != null)
//        {
//            hibernateConfig.setProperty("hibernate.generate_statistics", 
//                hibernateSettings.isGenerateStatistics().toString());
//        }
        
        hibernateConfig.setProperty("hibernate.connection.datasource", 
                DataSourceProvider.TAOGONG_DATASOURCE_JNDI_KEY);
        hibernateConfig.setProperty("hibernate.dialect", dialect);
        
        addMappings(hibernateConfig);  
        
//        JavaAssistHelper.createJavaAssistClassLoader().get(null);
        Thread.currentThread().setContextClassLoader(JavaAssistHelper.createJavaAssistClassLoader().get(null));
//        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
        SessionFactory sf = hibernateConfig.buildSessionFactory();
        
        isUpdated=false;
        
        return sf;
    }

    @Override
    public String getDialect()
    {
        return dialect;
    }
    
    @Override
    public boolean isUpdated()
    {
        return isUpdated;
    }
    
    
    public void addMappings(Configuration cfg)
    {
        //Object[] providers = context.locateServices("MappingProviders");
        //for (Object o : providers)
    	for (MappingProvider provider : mappingProviders)
        {
            //MappingProvider provider = (MappingProvider) o;
            for (Class<?> cls : provider.getEntityClasses())
            {
                cfg.addClass(cls);
                try
                {
                    cls.newInstance();
                }
                catch (InstantiationException e)
                {
                    e.printStackTrace();
                }
                catch (IllegalAccessException e)
                {
                    e.printStackTrace();
                }
            }
            
            for (URL url : provider.getMappings())
            {
                cfg.addURL(url);
            }
        }
    }
}
